/**
 * AsynImageLoader.java
 * Create Version: 1.0
 * Author: 徐舟骏
 * Create Date: 2012-5-9
 */
package ysyh55.android.base.util;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.lang.ref.SoftReference;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Handler;
import android.os.Message;
import android.util.Log;
import android.widget.ImageView;

import ysyh55.android.base.exception.HttpException;
import ysyh55.android.base.http.HttpClient;
import ysyh55.android.base.http.HttpResponse;

/**
 * AsynImageLoader 异步加载图片资源类
 * 
 * @author 徐舟骏
 */
public class AsynImageLoader {
	private static final String tag = "AsynImageLoader";

	/**
	 * 缓存下载过的图片的Map
	 */
	private Map<String, SoftReference<Bitmap>> caches = new HashMap<String, SoftReference<Bitmap>>();
	/**
	 * 下载图片用
	 */
	private HttpClient httpClient;
	/**
	 * 任务队列
	 */
	private List<Task> taskQueue = new ArrayList<Task>();
	/**
	 * 主进程
	 */
	private Runnable runnable;
	/**
	 * 事件处理
	 */
	private Handler handler;

	public AsynImageLoader(HttpClient client) {
		this.httpClient = client;

		this.runnable = new Runnable() {
			@Override
			public void run() {
				while (true) {
					while (taskQueue.size() > 0) {
						Task currentTask = taskQueue.remove(0);

						if (!caches.containsKey(currentTask.url) || NullUtils.isNull(caches.get(currentTask.url).get())) {
							InputStream is = null;
							try {
								synchronized (httpClient) {
									HttpResponse rp = httpClient.get(currentTask.url);
									is = rp.asStream();
									Bitmap bitmap = BitmapFactory.decodeStream(is);
									if (NullUtils.isNotNull(bitmap)) {
										caches.put(currentTask.url, new SoftReference<Bitmap>(bitmap));
									}
									Log.i(tag, "load from url: " + currentTask.url);
								}
							} catch (HttpException e) {
								currentTask.isValidUrl = false;
								Log.i(tag, "error occured while loading from: " + currentTask.url);
							} catch (IOException e) {
								e.printStackTrace();
							} catch (Exception e) {
								Log.i(tag, "error occured while loading from2: " + currentTask.url);
							} finally {
								if (is != null) {
									try {
										is.close();
									} catch (IOException e) {
									}
								}
							}
						} else {
							Log.i(tag, "already have.");
						}

						Message msg = handler.obtainMessage();
						msg.obj = currentTask;
						// 发送消息回主线程
						handler.sendMessage(msg);
					}

					// 如果队列为空,则令线程等待
					synchronized (runnable) {
						try {
							this.wait();
						} catch (InterruptedException e) {
							e.printStackTrace();
						}
					}
				}
			}
		};

		this.handler = new Handler() {
			@Override
			public void handleMessage(Message msg) {
				// 子线程中返回的下载完成的任务
				Task task = (Task) msg.obj;
				task.loadDone();
			}
		};

		new Thread(this.runnable).start();
	}

	/**
	 * 加载图片
	 * 
	 * @param imageView
	 *          需要延迟加载图片的对象
	 * @param url
	 *          图片的URL地址
	 * @param resId
	 *          图片加载过程中显示的图片资源
	 */
	public void showImageAsyn(SoftReference<ImageView> imageView, String url, Integer resId) {
		if (this.caches.containsKey(url) && NullUtils.isNotNull(this.caches.get(url).get())) {
			Bitmap bitmap = this.caches.get(url).get();
			imageView.get().setImageBitmap(bitmap);
			Log.i(tag, "load from cach.");
		} else {
			imageView.get().setImageResource(resId);
			this.addTask(imageView, url, resId);
		}
	}

	/**
	 * 加载图片
	 * 
	 * @param imageView
	 *          需要延迟加载图片的对象
	 * @param url
	 *          图片本地地址
	 * @param resId
	 *          图片加载过程中显示的图片资源
	 */
	public void showImageFromLocal(SoftReference<ImageView> imageView, String url, Integer resId) {
		if (this.caches.containsKey(url) && NullUtils.isNotNull(this.caches.get(url).get())) {
			Bitmap bitmap = this.caches.get(url).get();
			imageView.get().setImageBitmap(bitmap);
			Log.i(tag, "load from cach.");
		} else {
			imageView.get().setImageResource(resId);
			// 本地加载

			FileInputStream is = null;
			try {

				is = new FileInputStream(new File(url));
				
				Bitmap bitmap = BitmapFactory.decodeStream(is);
				if (NullUtils.isNotNull(bitmap)) {
					caches.put(url, new SoftReference<Bitmap>(bitmap));
				}
				Log.i(tag, "load from localpath: " + url);
			} catch (Exception e) {
				Log.i(tag, "error occured while loading from: " + url);
			} finally {
				if (is != null) {
					try {
						is.close();
					} catch (IOException e) {
					}
				}
			}
			imageView.get().setImageBitmap(AsynImageLoader.this.caches.get(url).get());
		}
	}

	/**
	 * 添加下载任务
	 * 
	 * @param imageView
	 * @param url
	 * @param resId
	 */
	private void addTask(SoftReference<ImageView> imageView, String url, Integer resId) {
		this.taskQueue.add(new Task(url, imageView, resId));
		synchronized (runnable) {
			runnable.notify();
		}
	}

	private class Task {
		/**
		 * 下载任务的下载路径
		 */
		String url;
		/**
		 * 加载图片的视图
		 */
		SoftReference<ImageView> imageView;
		/**
		 * 默认加载资源
		 */
		Integer resId;
		/**
		 * URL是否有效
		 */
		Boolean isValidUrl;

		private Task(String url, SoftReference<ImageView> imageView, Integer resId) {
			this.url = url;
			this.imageView = imageView;
			this.resId = resId;
			this.isValidUrl = true;
		}

		public void loadDone() {
			if (NullUtils.isNotNull(this.imageView.get())) {
				if (AsynImageLoader.this.caches.containsKey(url)
				    && NullUtils.isNotNull(AsynImageLoader.this.caches.get(this.url).get())) {
					this.imageView.get().setImageBitmap(AsynImageLoader.this.caches.get(this.url).get());
				} else {
					this.imageView.get().setImageResource(resId);
					if (this.isValidUrl) {
						AsynImageLoader.this.addTask(imageView, url, resId);
					}
				}
			}
		}
	}
}
